import configparser
import zipfile
import py7zr
import rarfile
import os
from threading import Thread

class BatchUnzip:
    def OnStart(self):
        config_file_path = "unzipconfig_pr.ini"
        print("[INFO] Starting...")
        self.error_log="error.log"
        try:
            print("[INFO] importing config from ", config_file_path)
            conf = configparser.ConfigParser()
            conf.read(config_file_path, encoding="UTF-8")
            self.root_path = conf["BATCH_UNZIP"]["root_path"]
            password_spliter = conf["BATCH_UNZIP"]["password_spliter"]
            passwords = conf["BATCH_UNZIP"]["passwords"]
            self.out_path = conf["BATCH_UNZIP"]["out_path"]
            self.password_list = passwords.split(password_spliter)
            self.error_log=conf["BATCH_UNZIP"]["error_path"]
        except Exception as e:
            print(e)
            return False
        return True

    def _rarFile(self, fromPath, toPath, pwds):
        succeed = False
        for pwdd in pwds:
            if succeed:
                break
            try:
                rf = rarfile.RarFile(fromPath)
                rf.extractall(path=toPath, pwd=pwdd)
                print("ext ", fromPath)
                print("pwd ", pwdd)
                print("out ", toPath)
                succeed = True
            except Exception as e:
                print(e)
                continue
        if not succeed:
            filep = open(self.error_log, mode="a+")
            filep.write(str(fromPath)+"\n")
            filep.close()
            print("[FAIL]", fromPath)

    def _7zFile(self, fromPath, toPath, pwds):
        succeed = False
        for pwdd in pwds:
            if succeed:
                break
            try:
                rf = py7zr.SevenZipFile(fromPath, mode='r', password=pwdd)
                rf.extractall(toPath)
                print("ext ", fromPath)
                print("pwd ", pwdd)
                print("out ", toPath)
                succeed = True
            except Exception as e:
                # print(e)
                continue
        if not succeed:
            pass
            # filep = open(self.error_log, mode="a+")
            # filep.write(str(fromPath)+"\n")
            # filep.close()
            # print("[FAIL]", fromPath)

    def _zipFile(self, fromPath, toPath, pwds):
        succeed = False
        
        for pwdd in pwds:
            if succeed:
                break
            try:
                with zipfile.ZipFile(fromPath) as zip_f:
                    zip_f.extractall(toPath,pwd=pwdd)
                    print("ext ", fromPath)
                    print("pwd ", pwdd)
                    print("out ", toPath)
                    succeed = True
            except Exception as e:
                # print(e)
                continue
        if not succeed:
            filep = open(self.error_log, mode="a+")
            filep.write(str(fromPath)+"\n")
            filep.close()
            print("[FAIL]", fromPath)

    def _ChagneToToPath(self, currentRoot):
        splited =  os.path.split(currentRoot)
        return self.out_path + splited[len(splited) - 1]
    
    def _pwdsGenerate(self, alphaBet="", pwdExactLen = 0, prefix=""):
        print("len = ", pwdExactLen)
        maxPwdCount = len(alphaBet)**(pwdExactLen)
        print("allPwdCount = ", maxPwdCount)
        allPwd = []
        for i in range(0, maxPwdCount):
            allPwd.append(prefix)
        for thisCharIndex in range(0, pwdExactLen):
            currentPwdIndex = 0
            updateCounter = len(alphaBet)**thisCharIndex
            while (currentPwdIndex + updateCounter) <= maxPwdCount:
                for alpha in alphaBet:
                    for i in range(0, updateCounter):
                        allPwd[currentPwdIndex + i] += alpha
                    currentPwdIndex += updateCounter
        return allPwd
    
    def _pwdStepIn(self, currentPwd="", alphaBet=""):
        allLast = True
        for a in currentPwd:
            if not alphaBet.index(a) == len(alphaBet) - 1:
                allLast = False
                break
        if allLast:
            return ""
        i = len(currentPwd) - 1
        res = currentPwd
        while i >= 0:
            thisAlpha = currentPwd[i]
            thisIndex = alphaBet.index(thisAlpha)
            nextIndex = thisIndex + 1
            tempList  = list(res)
            if nextIndex == len(alphaBet):
                nextIndex = 0
            tempList[i] = alphaBet[nextIndex]
            res = "".join(tempList)
            i -= 1
            if not nextIndex == 0:
                break
        return res

    def BatchUnzip(self):
        filep = open(self.error_log, mode="a+")
        filep.write(str(233333))
        filep.close()
        print("[INFO] Start Unzip!")
        print("[CONF] root path is ", self.root_path)
        print("[CONF] pass is ", self.password_list)
        print("[CONF] out path is ", self.out_path)
        for root, dirs, files in os.walk(self.root_path):
            # root 表示当前正在访问的文件夹路径
            # dirs 表示该文件夹下的子目录名list
            # files 表示该文件夹下的文件list
            # 遍历文件
            toPath = self._ChagneToToPath(root)
            for f in files:
                current_path = os.path.join(root, f)
                print(current_path)
                if current_path.endswith("rar"):
                    self._rarFile(current_path, toPath, self.password_list)
                elif current_path.endswith("zip"):
                    self._zipFile(current_path, toPath, self.password_list)
                elif current_path.endswith("7z"):
                    self._7zFile(current_path, toPath, self.password_list)

    def BruteForce(self):
        testPkgPath = "E:\TEMP\pwd.7z"
        outPath = "E:\TEMP"
        alphaBet = "AaBbCcDdEeFfGgHhIiJjKklLMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890"
        exactPwdLen = 10
        print("-- BruteForce --")
#         XTST:
# www.temptup.com/star/gQyxg50EJc
# XTST:
# www.temptup.com/channel/20eozRTD2U

        prefix = "www.temptup.com/channel/"
        curPwd = "AAAAAAAAAA"
        curPwd = "111"
        self._7zFile(fromPath=testPkgPath, toPath=outPath, pwds=[prefix + curPwd])
        counter = 0
        threadCount = 20
        nexPwds = []
        while True:
            for i in range(threadCount):
                nextPwd = self._pwdStepIn(currentPwd=curPwd, alphaBet=alphaBet)
                if not nextPwd == "":
                    nexPwds.append(nextPwd)
                counter += 1
            for nextPwd in nexPwds:
                self._7zFile(fromPath=testPkgPath, toPath=outPath, pwds=[prefix + nextPwd])
            if counter > 0:
                counter = 0
                print("tried to: ", nextPwd)
            if len(nexPwds) == 0:
                break
        print("-- BruteForce end --")

if __name__ == "__main__":
    print("-- BatchUnZipper --")
    t = BatchUnzip()
    # if not t.OnStart():
    #     print("[ERROR] Start fail")
    #     exit()
    # print("[INFO] Start succeed")
    # t.BatchUnzip()
    t.BruteForce()